package com.zhny.aiot.zbsyb.insect.plugin;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zhny.aiot.plugin.ICenterFacilities;
import com.zhny.aiot.plugin.IDeviceFactory;
import com.zhny.aiot.plugin.core.utils.MessageUtils;
import com.zhny.aiot.plugin.model.DeviceEntity;
import com.zhny.aiot.plugin.model.MessageEntry;
import com.zhny.aiot.plugin.model.MessageType;
import com.zhny.aiot.plugin.model.TaskEntity;
import com.zhny.aiot.plugin.web.WebDevice;
import com.zhny.aiot.zbsyb.insect.plugin.result.InsectData;
import com.zhny.aiot.zbsyb.insect.plugin.result.InsectToken;
import com.zhny.aiot.zbsyb.insect.plugin.result.InsectUserInfo;
import io.netty.util.internal.StringUtil;
import com.zhny.aiot.zbsyb.insect.plugin.model.InsectStoreEntry;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.pf4j.util.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URISyntaxException;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;

public class InsectDevice extends WebDevice<InsectConfig> {

    private static final Logger log=LoggerFactory.getLogger (InsectStoreEntry.class);
    private InsectToken token;
//    private Long deviceId;

//    private Map<String, String> configMap=new HashMap<> ();

    public InsectDevice(IDeviceFactory<InsectConfig> factory, ICenterFacilities centerFacilities, DeviceEntity entity) {
        super (factory, centerFacilities, entity);
    }

    @Override
    protected void onRequestHttp(TaskEntity taskEntity, CloseableHttpClient closeableHttpClient) {
        if(isTokenExpires ()) {
            this.token=onTokenHttp (closeableHttpClient);
        }
//        onConfigResponse (closeableHttpClient);
        successResponse (closeableHttpClient);
    }

    private boolean isTokenExpires() {
        if(token == null)
            return true;
        Long oldTimeStamp=token.getTime ();
        Long currentTimeStamp=System.currentTimeMillis ();
        Long expires=86400L;
        if(((currentTimeStamp-oldTimeStamp) / 1000)>=expires)
            return true;
        return false;
    }

    private InsectToken onTokenHttp(CloseableHttpClient httpClient) {
        log.info ("execute Insect soil api token request!");
        URIBuilder uriBuilder=null;
        InsectConfig config=this.getConfig ();
        if(StringUtils.isNullOrEmpty (config.getHost ()))
            return null;
        String host=config.getHost ().contains ("http://") ? config.getHost () : "http://"+config.getHost ();

        try {
            uriBuilder=new URIBuilder (host+"/loginFree");
            Map<String, Object> param=new HashMap<String, Object> () {{
                put ("username", config.getUserName ());
                put ("password", config.getPassword ());
            }};
            HttpPost httpPost=new HttpPost (uriBuilder.build ());
            String requestBody=serialize (param);
            if(StringUtils.isNullOrEmpty (requestBody))
                return null;
            httpPost.setEntity (new StringEntity (requestBody));
            httpPost.addHeader ("Content-Type", "application/json");
            try (CloseableHttpResponse response=httpClient.execute (httpPost)) {
                String body=EntityUtils.toString (response.getEntity ());
                InsectToken newToken=mapTo (body, new TypeReference<InsectToken> () {
                });
                if(newToken == null)
                    throw new RuntimeException ("Insect token api result map to error !");
                newToken.setTime (System.currentTimeMillis ());
                return newToken;
            } catch (ClientProtocolException e) {
                throw new RuntimeException (e);
            } catch (ConnectTimeoutException e) {
                throw new RuntimeException ("请求连接超时");
            } catch (IOException e) {
                throw new RuntimeException (e);
            }
        } catch (URISyntaxException e) {
            throw new RuntimeException (e);
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException (e);
        }
    }

//    private void onConfigResponse(CloseableHttpClient httpClient) {
//        log.info ("read Insect config api response!");
//        URIBuilder uriBuilder=null;
//        InsectConfig config=this.getConfig ();
//        if(StringUtils.isNullOrEmpty (config.getHost ()))
//            throw new RuntimeException ("Insect host is null !");
//        if(StringUtils.isNullOrEmpty (config.getSn ()))
//            throw new RuntimeException ("Insect sn is null !");
//        if(this.token == null) {
//            throw new RuntimeException ("Insect token is null !");
//        }
//        String host=config.getHost ().contains ("http://") ? config.getHost () : "http://"+config.getHost ();
//        try {
//            String httpUrl=host+"/permi/getAllPermiList";
//            uriBuilder=new URIBuilder (httpUrl);
//            HttpGet httpGet=new HttpGet (uriBuilder.build ());
//            httpGet.addHeader ("Authorization", this.token.getToken ());
//            try (CloseableHttpResponse response=httpClient.execute (httpGet)) {
//                String body=EntityUtils.toString (response.getEntity ());
//                InsectUserInfo result=mapTo (body, new TypeReference<InsectUserInfo> () {
//                });
//                if(result == null) {
//                    log.error ("{}Insect config api result map to error !", this.getDeviceEntity ().getName ());
//                    return;
//                }
//                onSetMap (result.getData (), config.getSn ());
//            } catch (ClientProtocolException e) {
//                throw new RuntimeException (e);
//            } catch (ConnectTimeoutException e) {
//                throw new RuntimeException ("请求连接超时");
//            } catch (IOException e) {
//                throw new RuntimeException (e);
//            }
//        } catch (URISyntaxException e) {
//            throw new RuntimeException (e);
//        }
//    }
//
//    private void onSetMap(JSONObject data, String deviceNo) {
//        if(data.containsKey ("device_permi")) {
//            JSONArray array=data.getJSONArray ("device_permi");
//            for (int i=0; i<array.size (); i++){
//                JSONObject item=array.getJSONObject (i);
//                if(item.containsKey ("manualId")) {
//                    String id=item.getString ("manualId");
//                    if(id.equals (deviceNo)) {
//                        this.deviceId=item.getLong ("deviceId");
//                        return;
//                    }
//                }
//            }
//        }
//    }


    private void successResponse(CloseableHttpClient httpClient) {
        log.info ("execute Insect soil api data request!");
        URIBuilder uriBuilder=null;
        InsectConfig config=this.getConfig ();
        if(StringUtils.isNullOrEmpty (config.getHost ()))
            throw new RuntimeException ("Insect host is null !");
        if(this.token == null) {
            throw new RuntimeException ("Insect no login !");
        }
//        if(this.deviceId == null) {
//            throw new RuntimeException ("Insect deviceid is null !");
//        }
        String host=config.getHost ().contains ("http://") ? config.getHost () : "http://"+config.getHost ();
        try {
            uriBuilder=new URIBuilder (host+"//device/photo/query");
            uriBuilder.addParameter ("pageNum","1");
            uriBuilder.addParameter ("pageSize","1");
            uriBuilder.addParameter ("deviceName",config.getSn ());
            uriBuilder.addParameter ("AscOrDesc","true");
            HttpGet httpGet=new HttpGet (uriBuilder.build ());
            httpGet.addHeader ("Authorization", this.token.getToken ());
            try (CloseableHttpResponse response=httpClient.execute (httpGet)) {
                String body=EntityUtils.toString (response.getEntity ());
                InsectData result=mapTo (body, new TypeReference<InsectData> () {
                });
                if(result != null) {
                    MessageEntry messageEntry=MessageUtils.createMessageEntry (this.getId ());
                    messageEntry.setType (MessageType.RESULT);
                    if(result.getRows ().size () == 0)
                        return;
                    InsectStoreEntry entry=getStoreEntry (result);
                    if(entry != null) {
                        messageEntry.setData (entry);
                        nofity (messageEntry);
                        save (entry);
                        saveReal (entry);
                    }
                }

            } catch (ClientProtocolException e) {
                throw new RuntimeException (e);
            } catch (ConnectTimeoutException e) {
                throw new RuntimeException ("请求连接超时");
            } catch (IOException e) {
                throw new RuntimeException (e);
            }
        } catch (URISyntaxException e) {
            throw new RuntimeException (e);
        }
    }

    private <T> T mapTo(String body, TypeReference<T> cls) {
        if(StringUtil.isNullOrEmpty (body))
            return null;
        ObjectMapper mapper=new ObjectMapper ();
        try {
            mapper.configure (DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
            T obj=mapper.readValue (body, cls);
            return obj;
        } catch (IOException e) {
            return null;
        }
    }

    private String serialize(Object obj) {
        if(obj == null)
            return null;
        ObjectMapper mapper=new ObjectMapper ();
        try {
            return mapper.writeValueAsString (obj);
        } catch (IOException e) {
            return null;
        }
    }

    private InsectStoreEntry getStoreEntry(InsectData result) {
        InsectStoreEntry entry=new InsectStoreEntry ();
        JSONObject object=result.getRows ().getJSONObject (0);
        if(object == null)
            return null;
        if(object.containsKey ("resultPath")) {
            entry.setResultUrl (this.getConfig ().getHost ()+object.getString ("resultPath"));
        }
        return entry;
    }
}
